<?php
class auth {
	private $default = null;
	private $providers = null;
	
	private $authDebug = false;
	
	function check_access($default,$dblayer,$providers) {
		$authenticated = false;
	  if ($this->authDebug) {
	    print("Beginning Access Check");
	  }
			if (isset($_SESSION['SH-UID'])) {
				// session is set, check the validity of the SH-UID value
					//do stuff!
					if ($this->authDebug) {
	          print("Session set, checking user");
	        }
					$UID = GetParam('SH-UID','text','SESSION');
					$reg = $dblayer->query("USER",sprintf("select UID from users where UID = '%s' and enabled = 1",$UID));
					if ($reg->num_rows) {
					  if ($this->authDebug) {
	            print("Authenticated");
	          }
					  $authenticated = true;
					} else {
					  if ($this->authDebug) {
	            print("Authentication failed");
	          }
					  $unset($_SESSION['SH-UID']);
					}
			} else if ( (isset($_POST['sh-un'])) and (isset($_POST['sh-pw'])) ) {
				//
				if ($this->authDebug) {
	          print("Performing Authentication.");
	      }
				$authenticated = $this->authenticate($default,$dblayer,$providers);
			} else {
				//  calling the login page handled by bootstrap.php
			}
		
		return $authenticated;
	}
	
	function login() {
		//produce a login page
		$html = "";
			$html .= "<form action='?' method='post'>\n";
				$html .= "<p>\n";
					$html .= "Username: <input type='text' name='sh-un' id='sh-un' /><br />\n";
					$html .= "Password: <input type='password' name='sh-pw' id='sh-pw' /><br />\n";
					$html .= "<input type='submit' name='submit' value='Login' />\n";
				$html .= "</p>\n";
			$html .= "</form>\n";
		return $html;
	}
	
	function authenticate(&$default,&$dblayer,$providers) {
	/*
		$default = configuration information for the local user database
		$providers = class for providing the extra authentication sources' configurations
		$username = current POSTed username (sanitised)
		$password = current POSTed password (sanitised)
	*/
				$username = GetParam('sh-un','text','POST');
				$password = GetParam('sh-pw','text','POST');
	$authenticated = false;
		$userdb = $default->param("USER","dbname");
		$userconn = $default->param("USER","dbconn");
		$lpassword = md5($password);
		//$userlookup =  new mysqldb;
		//$userlookup->setquery($userdb,$userconn,sprintf("select * from users where username='%s' and password='%s' and source='local' ",$username,$lpassword));
		
		$userlookup = $dblayer->query("USER",sprintf("select * from users where username='%s' and password='%s' and source='local' ",$username,$lpassword));
			if ($userlookup->num_rows) {
			  if ($this->authDebug) {
	            print("Local User found");
	      }
			  $row = $userlookup->fetch_object();
				// authenticated
				if ($row->enabled == 1) {
					$UID = $row->UID;
					$authenticated = true;
				}
			}
			if ($this->authDebug) {
	            print("Authenticated Local: {$authenticated}");
	    }
		$archived = false;
		if (!$authenticated) {
			///$archive = new mysqldb;
			//$archive->setquery($userdb,$userconn,sprintf("select * from archived_users where username='%s'",$username));
			$archive = $dblayer->query("USER",sprintf("select * from archived_users where username='%s'",$username));
				if ($archive->num_rows) {
					//archived
					$archived = true;
				}
				if ($this->authDebug) {
	            print("Authenticated Archived User: {$archived}");
	      }
		}
		if (!$archived) {
			if ($authenticated) {
				//local user, setup session
				if (isset($UID)) {
					$_SESSION['SH-UID'] = $UID;
				}
				/* TODO */
			} else {
				//$remotelookup = new mysqldb;
				//$remotelookup->setquery($userdb,$userconn,sprintf("select * from users where username = '%s' and source != 'local' ",$username));
				$remotelookup = $dblayer->query("USER",sprintf("select * from users where username = '%s' and source != 'local' ",$username));
				if ($remotelookup->num_rows) {
				  $row = $remotelookup->fetch_object();
				if ($row->enabled == 1) {
					//we found the username in the db, lookup the authentication source
					$authSource = $providers->provider_config($row->source);
					$type = $providers->type($row->source);
					$label = $row->source;
					if ($authSource) {
						switch ($type) {
						case "mysql":
						//connect to database
						$dbs = new dbloader;
						$dbs->add($label,$authSource['database']);
						if (isset($authSource['fields']['table'])) {
							$tableField = $authSource['fields']['table'];
							if (isset($authSource['fields']['id'])) {
								$idField = $authSource['fields']['id'];
								if (isset($authSource['fields']['username'])) {
									$unField = $authSource['fields']['username'];
									if (isset($authSource['fields']['password'])) {
										if (isset($authSource['encryption'])) {
											switch ($authSource['encryption']) {
											case "md5":
												$password = md5($password);
											break;
											} // switch encryption
										}// if isset encryption
										$pwField = $authSource['fields']['password'];
										$LQuery = sprintf("select %s,%s from %s where %s='%s' and %s='%s'",$idField,$unField,$tableField,$unField,$username,$pwField,$password);
										$mysqli = new mysqli($authSource['database']['dbhost'],$authSource['database']['dbuser'],$authSource['database']['dbpass'],$authSource['database']['dbname']);
                		$Lresult = $mysqli->query($LQuery);
              		  
										if ($Lresult->num_rows) {
											// we managed to authenticate the user
											//lookup in local db
											$_SESSION['SH-UID'] = $row->UID;
											$authenticated = true;
										}
										$mysqli->close();
										//$lookup->disposequery();
									} // if isset fields password
								} // if isset fields username
							} // if isset fields id 
						} // if isset fields table
						break;
						case "ldap":
					
						//break;
						case "ldaps":
							//die("We are entering ldaps");
							if ( (isset($authSource['server']['host'])) and (isset($authSource['server']['port'])) ) {
								$ldap_conn = ldap_connect($authSource['server']['host'],$authSource['server']['port']);
								if ($ldap_conn) {
									if (isset($authSource['ldap_provider'])) {
										switch ($authSource['ldap_provider']) {
											case "ms-active-directory":
												ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION,3);
												ldap_set_option($ldap_conn, LDAP_OPT_REFERRALS,0);
											break;
										}//switch
										if ( (isset($authSource['auth']['fqdn'])) ) {
											$bound = @ldap_bind($ldap_conn,$username."@".$authSource['auth']['fqdn'],$password);
											if ($bound) {
												$_SESSION['SH-UID'] = $row->UID;
												$authenticated = true;
											} else {
												// not authenticated
											}
										}
									}// if isset ldap_provider
								} else {
									//could not connect to ldap server
								}
							} else {
								// host and port not set
							}
						break;
						} // switch (type)
					} // if (authSource) 
					}//if enabled
				} else { // if (remotelookup totalRows) 
						// get a list of sources to look through and if a user is authenticated -> add from that source.
						if ($this->authDebug) {
	            print(" Searching for remote user to synchronise ");
	          }
						$authlabels = $providers->labels();
						$control = count($authlabels);
						if ($control) {
							$lookup = new mysqldb;
							$control = count($authlabels);
							$found = false;
							$i = 0;
							do {
							$label = $authlabels[$i];
								// try each auth source in order
								$authSource = $providers->provider_config($label);
								$type = $providers->type($label);
								if ($authSource) {
									switch ($type) {
									case "mysql":
										//connect to database
										$dbs = new dbloader;
										$dbs->add($label,$authSource['database']);
										$dblayer->add_layer($label,$authSource['database']);
										if (isset($authSource['fields']['table'])) {
											$tableField = $authSource['fields']['table'];
											if (isset($authSource['fields']['id'])) {
												$idField = $authSource['fields']['id'];
												if (isset($authSource['fields']['username'])) {
													$unField = $authSource['fields']['username'];
													if (isset($authSource['fields']['password'])) {
														if (isset($authSource['encryption'])) {
															switch ($authSource['encryption']) {
															case "md5":
																$password = md5($password);
															break;
															} // switch encryption
														}// if isset encryption
														$pwField = $authSource['fields']['password'];
															/* TODO : we should have the ability to specify extra conditions, for example, the user may have an enabled field  */
															$mysqli = new mysqli($authSource['database']['dbhost'],$authSource['database']['dbuser'],$authSource['database']['dbpass'],$authSource['database']['dbname']);
															if (!(isset($authSource['fields']['display_name']))) {
																$LQuery = sprintf("select %s,%s from %s where %s='%s' and %s='%s'",$idField,$unField,$tableField,$unField,$username,$pwField,$password);
                            		$Lresult = $mysqli->query($LQuery);
					                          
															} else {
																$rnField = $authSource['fields']['display_name'];
																$LQuery = sprintf("select %s,%s,%s from %s where %s='%s' and %s='%s'",$idField,$unField,$rnField,$tableField,$unField,$username,$pwField,$password);
																$Lresult = $mysqli->query($LQuery);
															}
															$mysqli->close();
														if ($Lresult->num_rows) {
	                            $lookup = $Lresult->fetch_object();
															// we managed to authenticate the user
															$info = array();
															$info['username'] = $username;
															if (!(isset($authSource['fields']['display_name']))) {
																$info['realname'] = $lookup->$rnField;
															} else {
																$info['realname'] = "";
															}
															$user = synchronise_user($dblayer,$providers,$info,$label);
															$_SESSION['SH-UID'] = $user;
															$authenticated = true;
															$found = true;
														} else {
														  
														}
														//$lookup->disposequery();
													} // if isset fields password
												} // if isset fields username
											} // if isset fields id 
										} // if isset fields table
									break;
									case "ldap":
								
									//break;
									case "ldaps":
										if ( (isset($authSource['server']['host'])) and (isset($authSource['server']['port'])) ) {
											$ldap_conn = ldap_connect($authSource['server']['host'],$authSource['server']['port']);
											if ($ldap_conn) {
												if (isset($authSource['ldap_provider'])) {
													switch ($authSource['ldap_provider']) {
														case "ms-active-directory":
															ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION,3);
															ldap_set_option($ldap_conn, LDAP_OPT_REFERRALS,0);
														break;
													}//switch
													if ( (isset($authSource['auth']['fqdn'])) ) {
														$bound = ldap_bind($ldap_conn,$username."@".$authSource['auth']['fqdn'],$password);
															if ($bound) {
																$info = array();
																$info['username'] = $username;
																$info['realname'] = "";
																$lresult = ldap_search($ldap_conn,$authSource['auth']['dn'],$authSource['auth']['username_label']."=".$username);
																$lcount = ldap_count_entries($ldap_conn,$lresult);
																if ($lcount) {
																	$fe = ldap_get_entries($ldap_conn,$lresult);
																	if (isset($fe[0]['cn'][0])) {
																		$info['realname'] = $fe[0]['cn'][0];
																	}
																	ldap_free_result($lresult);
																}
																$user = synchronise_user($dblayer,$providers,$info,$label);
																$_SESSION['SH-UID'] = $user;
																$authenticated = true;
																$found = true;
																ldap_unbind($ldap_conn);
															} else {
																// not authenticated
															}
													}
												}// if isset ldap_provider
											} else {
												//could not connect to ldap server
											}
										} else {
											// host and port not set
										}
									break;
									}
								}
								$i++;
							} while (($i < $control) and (!$found)) ;
						}
				}
				//$remotelookup->disposequery();
			}//if authenticated ... else
		}// if not archived
		return $authenticated;
	}
	
	function log_failure() {
		//should this be deprectated??
	}
	
}
?>
